/*
 *  ObjectRef.h
 *  vorpal
 *
 *  Created by rwebb on 8/04/09.
 *
 */

#ifndef HANDLE_H
#define HANDLE_H

#include <typeinfo>
#include "ErrorCodes.h"
#include "Common.h"

namespace Vorpal{

/// Used to manage reference counts in the C++ code, auto incrementing and decrementing reference
template< class Type >
class Handle{
public:
	~Handle(){
		if(ptr){ ptr->DecCount(); }
	}
	
	Handle() : ptr(0){ }
	
	Handle(Type *newPtr) : ptr(0){ 
		Attach(newPtr);
	}

	Handle(const Handle<Type> &other) : ptr(0){
		Attach(other.ptr);
	}
	
	Handle<Type>& operator=(const Handle<Type> &rhs){
		Attach(rhs.ptr);
		return *this;
	}
	
	Handle<Type>& operator=(Type *rhs){
		Attach(rhs);
		return *this;
	}	
	
	bool IsNull() const{ return ptr == 0; }
	
	Type* operator ->() const{ return ptr; }
	
	Type& operator*() const{ return *ptr; }
	
	//operator Type* () const{ return ptr; }
	
	Type* Ptr() const{ return ptr; }

	void Detach(){ Attach(0); }
	
	void Attach(Type *newPtr){
		if(newPtr == ptr){ return; } // safe self assignment
		if(ptr){
			ptr->DecCount();
		}
		ptr = newPtr;
		if(ptr){
			ptr->IncCount();
		}
	}
	
	bool operator==(const Handle<Type> &rhs) const{ return ptr == rhs.ptr; }
	bool operator!=(const Handle<Type> &rhs) const{ return ptr != rhs.ptr; }

private:		
	Type *ptr;
};

}
#endif // HANDLE_H

